<?php

namespace app\api\controller\audit;

use app\api\controller\Api;
use app\api\controller\order\Order;
use app\common\audit\logic\AuditProcessLogic;
use app\common\audit\logic\AuditResultLogic;
use app\common\audit\model\AuditComment;
use app\common\audit\model\AuditFlow;
use app\common\audit\model\AuditResult;
use app\common\system\logic\UserLogic;
use think\db\exception\DbException;
use think\Exception;
use util\Format;

class Process extends Api
{
    public function index()
    {
        $post = $this->request->post();
        $user = $this->request->user;

        list($cfg) = Format::pagination($post);
        $where = [];
        if (!empty($post['date_range'])) {
            $dateRange = Format::dateRange($post['date_range']);
            $where[] = ['create_time', 'between', $dateRange];
        }
        if (!empty($post['keyword'])) $where[] = ['AuditFlow.audit_no', '=', $post['keyword']];
        $where[] = ['audit_user_id', '=', $user['id']];
        if (isset($post['status']) && $post['status'] != '') $where[] = ['AuditFlow.status', '=', $post['status']];
        
        if ($post['type'] != '') {
            if ($post['type'] == 0) {
                $where[] = ['AuditFlow.status', '=', 0];
            } else {
                $where[] = ['AuditFlow.status', '>', 0];
            }
        }

        $hasWhere = [];
        if (!empty($post['audit_type'])) $hasWhere[] = ['AuditResult.audit_type', '=', $post['audit_type']];
        if (!empty($post['user_id'])) $hasWhere[] = ['AuditResult.create_user_id', 'in', $post['user_id']];
        if (!empty($post['company_id'])) $hasWhere[] = ['AuditResult.company_id', 'in', $post['company_id']];

        $model = AuditFlow::hasWhere('audit', $hasWhere);
        $model = $model->where($where);
        $pg = $model->with('audit')->order('id desc')->paginate($cfg);

        $rows = $pg->getCollection();
        foreach ($rows as $row) {
            $row->append(['auditor', 'status_text']);
            $row->audit->append(['company', 'tag', 'creator', 'order']);
        }

        $result['list'] = $rows;
        $result['pagination'] = Format::pgResult($pg);

        return success($result, '获取数据成功');
    }

    public function transfer()
    {
        $post = $this->request->post();
        if (empty($post['audit_flow_id']) || empty($post['user_id'])) return error([], '参数错误');
        $user = $this->request->user;
        if ($user['id'] == $post['user_id']) {
            return error([], "无法自己转交自己");
        }

        $model = new AuditFlow();
        $flow = $model->where('id', $post['audit_flow_id'])->find();
        if (empty($flow)) return error([], "审核项不存在");
        if ($user['id'] != $flow['audit_user_id']) {
            return error([], "无权转交");
        }

        $len = count($flow['transfer']);
        if ($len > 0) return error([], "已转{$len}次");

        $data = [];
        $data['audit_user_id'] = $post['user_id'];
        $userLogic = new UserLogic();
        $from = $userLogic->getUser($user['id'], ['id', 'realname', 'status']);
        $to = $userLogic->getUser($post['user_id'], ['id', 'realname', 'status']);
        $data['transfer'] = [
            'from' => $from,
            'to' => $to,
            'at' => date('Y-m-d H:i:s')
        ];

        try {
            $flow->save($data);
        } catch (DbException $e) {
            return error([], $e->getMessage());
        }

        return success([], "转交成功");
    }

    // 获取审核流程
    public function getProcess()
    {
        $post = $this->request->post();

        $data = [];
        $user = $this->request->user;

        // 设置审核条件
        $options = [];
        $options['type'] = $post['type'];
        $options['company_id'] = $post['company_id'];

        $logic = new AuditProcessLogic();
        $result['process'] = $logic->getAuditProcess($data, $user, $options);

        return success($result, "获取审核流程成功");
    }

    // 获取审核流程
    public function getResult()
    {
        $post = $this->request->post();
        $user = $this->request->user;

        $auditRsLogic = new AuditResultLogic();
        $audit = $auditRsLogic->getAuditRs($post['audit_no']);
        if (empty($audit)) return error([], "审核已经不存在");
        $audit->append(['creator', 'tag', 'audit_status']);
        $result['audit'] = $audit;

        $appends = [
            'Order' => ['category', 'customer', 'allocate', 'company', 'source', 'cooperation', 'user', 'store', 'hall', 'banquet_type', 'order_type_text', 'check_tag'],
            'OrderProduct' => ['category', 'company', 'product', 'user', 'check_tag'],
            'OrderAdditional' => ['company', 'category', 'product', 'user', 'check_tag'],
            'OrderIncome' => ['way', 'type', 'user', 'check_tag'],
            'OrderPay' => ['type', 'user', 'store', 'check_tag'],
            'OrderProtocol' => ['category', 'company', 'user', 'check_tag', 'type_tag'],
        ];

        $products = [];
        $source = $audit['source'];
        foreach ($source as $className => $row) {
            $class = new $className;
            $name = basename(str_replace('\\', '/', $className));
            $where = [];
            if (is_array($row)) {
                $where[] = ['id', 'in', $row];
                $productRows = $class->where($where)->select();
                if (isset($appends[$name])) {
                    foreach ($productRows as $row) {
                        $row->append($appends[$name]);
                    }
                }
                $products[$name] = $productRows;
            } else {
                $where[] = ['id', '=', $row];
                $productRow = $class->where($where)->find();
                if (isset($appends[$name])) {
                    $productRow->append($appends[$name]);
                }
                $products[$name] = $productRow;
            }
        }
        $result['products'] = $products;

        $flowModel = new AuditFlow();
        $rows = $flowModel->where('audit_no', $post['audit_no'])->select();
        foreach ($rows as $flow) {
            $flow->append(['auditor', 'status_text']);
        }
        $flows = $rows->toArray();
        $index = count($flows) - 1;
        $result['flow'] = $flows[$index];
        $flows = array_column($flows, null, 'audit_item_id');

        $process = $audit['process'];
        $current = 0;
        $commentModel = new AuditComment();
        foreach ($process as &$p) {
            $auditId = $p['id'];
            if (isset($flows[$auditId])) {
                $currentFlow = $flows[$auditId];
                $p['result'] = $currentFlow;
                $current += 1;
                $comments = $commentModel->where('flow_id', $currentFlow['id'])->order('id desc')->select();
                foreach ($comments as $comment) {
                    $comment->append(['user']);
                }
                $p['comments'] = $comments;
            }
        }
        $result['current'] = $current;
        $result['process'] = $process;
        $result['user'] = $user;

        return success($result);
    }

    public function getRejectData()
    {
        $post = $this->request->post();
        $user = $this->request->user;

        $auditRsLogic = new AuditResultLogic();
        $audit = $auditRsLogic->getAuditRs($post['audit_no']);
        if (empty($audit)) return error([], "审核已经不存在");
        $audit->append(['creator', 'tag', 'audit_status']);
        $result['audit'] = $audit;

        $appends = [
            'Order' => ['category', 'company', 'source', 'cooperation', 'user', 'store', 'hall', 'banquet_type', 'order_type_text', 'collects', 'check_tag'],
            'OrderProduct' => ['category', 'company', 'banquet', 'product', 'user', 'check_tag'],
            'OrderAdditional' => ['company', 'category', 'product', 'user', 'check_tag'],
            'OrderIncome' => ['way', 'type', 'user', 'check_tag'],
            'OrderPay' => ['type', 'user', 'check_tag'],
            'OrderProtocol' => ['category', 'company', 'user', 'type_tag', 'check_tag'],
            'OrderSettle' => ['company', 'category', 'product', 'user', 'check_tag']
        ];

        $products = [];
        $source = $audit['source'];
        foreach ($source as $className => $row) {
            $class = new $className;
            $name = basename(str_replace('\\', '/', $className));
            $where = [];
            if (is_array($row)) {
                $where[] = ['id', 'in', $row];
                $productRows = $class->where($where)->select();
                if (isset($appends[$name])) {
                    foreach ($productRows as &$row) {
                        $row->append($appends[$name]);
                        $row['check_no'] = '';
                        $row['check_status'] = 0;
                        $row['check_time'] = 0;
                    }
                }
                $products[$name] = $productRows;
            } else {
                $where[] = ['id', '=', $row];
                $productRow = $class->where($where)->find();
                if (isset($appends[$name])) {
                    $productRow->append($appends[$name]);
                }
                $productRow['check_no'] = '';
                $productRow['check_status'] = 0;
                $productRow['check_time'] = 0;
                $products[$name] = $productRow;
            }
        }
        $result['products'] = $products;

        return success($result);
    }

    public function accept()
    {
        $post = $this->request->post();
        $user = $this->request->user;

        if (empty($post['audit_flow_id'])) return error([], '参数错误');

        $flowModel = new AuditFlow();
        $flow = $flowModel->where('id', $post['audit_flow_id'])->find();
        if ($flow['audit_user_id'] != $user['id']) {
            return error([], "没有权限");
        }

        if ($flow['status'] > 0) {
            return error([], "请勿重复审批");
        }

        $flowModel->startTrans();
        try {
            $post['status'] = 1;
            $flow->save($post);
        } catch (DbException $e) {
            $flowModel->rollback();
            return error([], $e->getMessage());
        }

        $auditModel = new AuditResult();
        $audit = $auditModel->where('audit_no', $flow->audit_no)->find();
        $process = $audit->process;

        $processLogic = new AuditProcessLogic();
        try {
            list($cfg, $auditor, $isLast) = $processLogic->getNextAudit($process, $user, $flow['audit_item_id']);
        } catch (Exception $e) {
            $flowModel->rollback();
            return error([], $e->getMessage());
        }
        $source = $audit['source'];

        if ($isLast) { // 最后一个审批，审核结束
            $audit->save(['status' => 2]);
            foreach ($source as $className => $row) {
                try {
                    $where = [];
                    if (is_array($row)) {
                        $where[] = ['id', 'in', $row];
                    } else {
                        $where[] = ['id', '=', $row];
                    }
                    $class = new $className;
                    $checkData = [];
                    $checkData['check_no'] = $flow['audit_no'];
                    $checkData['check_status'] = 2;
                    $checkData['check_time'] = time();
                    $class->where($where)->save($checkData);
                } catch (DbException $e) {
                    $flowModel->rollback();;
                    return error([], $e->getMessage());
                }
            }

            switch ($audit['audit_type']) {
                case "order":
                    // 标记转单
                    $orderModel = new \app\common\order\model\Order();
                    $order = $orderModel->where('id', $audit['master_id'])->find();
                    if ($order['pid'] > 0) {
                        \app\common\order\model\Order::update(['transfer_status' => 1], ['id' => $order['pid']]);
                    }
                    break;
            }

            // 发送通知
            $notice = [];
            $notice['from_user_id'] = $user['id'];
            $notice['user_id'] = $audit['create_user_id'];
            $notice['type'] = 4;
            $notice['content'] = '您的审核已通过，请注意查看';
            $notice['options'] = [
                'audit_no' => $audit['audit_no'],
            ];
            $noticeModel = new \app\common\system\model\Notice();
            $noticeModel->save($notice);

            $flowModel->commit();
            return success([], "审核已完成");
        }

        // 创建下一个审批
        try {
            $data = [];
            $data['audit_id'] = $audit['id'];
            $data['audit_no'] = $flow['audit_no'];
            $data['operate_user_id'] = $auditor['id'];
            $data['audit_user_id'] = $auditor['id'];
            $data['audit_item_id'] = $cfg['id'];

            $subModel = new AuditFlow();
            $subModel->save($data);
        } catch (DbException $e) {
            $flowModel->rollback();;
            return error([], $e->getMessage());
        }
        $audit->save(['status' => 1]); // 修改当前审核状态为审核中
        foreach ($source as $className => $row) {
            try {
                $where = [];
                if (is_array($row)) {
                    $where[] = ['id', 'in', $row];
                } else {
                    $where[] = ['id', '=', $row];
                }
                $class = new $className;
                $checkData = [];
                $checkData['check_no'] = $flow['audit_no'];
                $checkData['check_status'] = 1;
                $checkData['check_time'] = time();
                $class->where($where)->save($checkData);
            } catch (DbException $e) {
                $flowModel->rollback();;
                return error([], $e->getMessage());
            }
        }
        $flowModel->commit();

        return success([], "审核成功");
    }

    public function reject()
    {
        $post = $this->request->post();
        $user = $this->request->user;

        if (empty($post['audit_flow_id'])) return error([], '参数错误');

        $flowModel = new AuditFlow();
        $flow = $flowModel->where('id', $post['audit_flow_id'])->find();
        if ($flow['audit_user_id'] != $user['id']) {
            return error([], "没有权限");
        }

        if ($flow['status'] > 0) {
            return error([], "请勿重复审批");
        }

        $flowModel->startTrans();
        try {
            $post['status'] = 2;
            $flow->save($post);
        } catch (DbException $e) {
            $flowModel->rollback();
            return error([], $e->getMessage());
        }

        $auditModel = new AuditResult();
        $audit = $auditModel->where('audit_no', $flow->audit_no)->find();
        $source = $audit['source'];
        // 设置驳回
        $audit->save(['status' => 3]);
        foreach ($source as $className => $row) {
            try {
                $where = [];
                if (is_array($row)) {
                    $where[] = ['id', 'in', $row];
                } else {
                    $where[] = ['id', '=', $row];
                }
                $class = new $className;
                $checkData = [];
                $checkData['check_no'] = $flow['audit_no'];
                $checkData['check_status'] = 3;
                $checkData['check_time'] = time();
                $class->where($where)->save($checkData);
            } catch (DbException $e) {
                $flowModel->rollback();;
                return error([], $e->getMessage());
            }
        }

        // 通知
        $notice = [];
        $notice['from_user_id'] = $user['id'];
        $notice['user_id'] = $audit['create_user_id'];
        $notice['type'] = 4;
        $notice['content'] = '您的审核已被驳回，请注意查看';
        $notice['options'] = [
            'audit_no' => $audit['audit_no'],
        ];
        $noticeModel = new \app\common\system\model\Notice();
        $noticeModel->save($notice);

        $flowModel->commit();
        return success([], "驳回成功");
    }
}